home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / MLRXSHL.ZIP / cmdshl.cmd < prev    next >
Encoding:
Text File  |  1996-02-22  |  35.9 KB  |  889 lines

  1. /* cmdshl.cmd - an improved cmd shell                          960222 */
  2. /* (c) martin lafaix 1994 - 1996                                      */
  3.  
  4. /* user dependant values */
  5. insertState = 1
  6. cmdQueue = 1
  7. impCD = 1
  8. nl = '0d0a'x
  9. defHelp = 'Use the DEFINE command to (re)define keyboard keys'nl||nl||,
  10.           'SYNTAX:    DEF key [value]'nl||,
  11.           '        DEFINE key [value]'nl||nl||,
  12.           '         key    The name of the key to be redefined.'nl||,
  13.           '         value  The new key value. It can be an internal command,'nl||,
  14.           '                OSNowait xxx or TEXT yyy.'nl||nl||,
  15.           'Examples:'nl||,
  16.           '         DEF F12 TEXT dir /w'nl||,
  17.           '      DEFINE F3  OSNOWAIT exit'nl||,
  18.           '         DEF F12'
  19. aliasHelp = 'Use the ALIAS command to view, add or remove an alias'nl||nl||,
  20.             'SYNTAX: ALIAS [LIST|alias=[string]|@file]'nl||nl||,
  21.             '         LIST    View all currently defined aliases.'nl||,
  22.             '         alias   An alias name (case sensitive).'nl||,
  23.             '         string  The new value for alias.'nl||,
  24.             '         file    A file containing one (or more) alias definitions.'nl||nl||,
  25.             'In an alias definition, %n[*] denotes command line parameters.'
  26. cmdHelp = 'Use the CMDSHL command to enhance your command shell.'nl||nl||,
  27.           'SYNTAX: CMDSHL [/I|/O] [/P profile] [/C cmd|/K cmd]'nl||nl||,
  28.           '         /I    Insert mode is the default.'nl||,
  29.           '         /O    Overstrike mode is the default.'nl||,
  30.           '         /P    Use the specified profile file.'nl||,
  31.           '         /C    Execute cmd and exit CMDSHL.'nl||,
  32.           '         /K    Execute cmd without exiting CMDSHL.'nl||nl||,
  33.           'By default, Insert mode is on and PROFILE.SHL is used as profile'nl||,
  34.           'file if it exists along the path specified by the DPATH environment'nl||,
  35.           'variable.'
  36. cdHelp = 'Enter CD -     To go back to the previous current directory'
  37. /* nothing to translate beyond this point */
  38.  
  39. /*====================================================================
  40.  * The Main Loop.
  41.  *====================================================================*/
  42. '@echo off'; trace off
  43.  
  44. call init
  45.  
  46. if arg() then
  47.    call doarg arg(1)
  48.  
  49. call profile
  50.  
  51. loop:
  52. do forever
  53.    call charout ,print()
  54.  
  55.    line = getline()
  56.  
  57.    if (eval(line) = 0) then
  58.       leave
  59. end /* do */
  60.  
  61. call terminate
  62.  
  63. exit
  64.  
  65. /*====================================================================  
  66.  * A cmd.exe-like Command Prompt.
  67.  *====================================================================*/
  68. print:             
  69.    prompt = value('PROMPT',,'OS2ENVIRONMENT')
  70.    if (prompt == '') then
  71.       prompt = '[$p]'
  72.  
  73.    str = ''
  74.  
  75.    do i = 1 to length(prompt)
  76.       key = substr(prompt,i,1)
  77.       if (key = '$') then
  78.          do
  79.          i = i+1; key = translate(substr(prompt,i,1))
  80.          select                               
  81.             when key = '$' then str = str||'$'
  82.             when key = 'A' then str = str||'&'
  83.             when key = 'B' then str = str||'|'
  84.             when key = 'C' then str = str||'(' 
  85.             when key = 'D' then str = str||date()
  86.             when key = 'E' then str = str||'1b'x
  87.             when key = 'F' then str = str||')' 
  88.             when key = 'G' then str = str||'>'                                                                      
  89.             when key = 'H' then str = str||'08'x                                                                            
  90.             when key = 'I' then str = str||'1b'x'[s'||'1b'x'[0;0H'helpColor1'1b'x'[K'helpstring||helpColor2'1b'x'[u'
  91.             when key = 'L' then str = str||'<'
  92.             when key = 'N' then str = str||filespec("d",directory())
  93.             when key = 'P' then str = str||directory()
  94.             when key = 'Q' then str = str||'='
  95.             when key = 'R' then str = str||rc
  96.             when key = 'S' then str = str||' '
  97.             when key = 'T' then str = str||time()
  98.             when key = 'V' then str = str||verString
  99.             when key = '_' then str = str||'0d0a'x
  100.          otherwise
  101.          end  /* select */
  102.          end
  103.       else     
  104.          str = str||key
  105.    end /* do */
  106.    return str
  107.  
  108. /*====================================================================  
  109.  * A cmd.exe-like Command Shell, w/ Filename Completion.
  110.  *====================================================================*/
  111. init:
  112.    if RxFuncQuery("SysLoadFuncs") then                       
  113.       do
  114.       call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
  115.       call SysLoadFuncs
  116.       end
  117.  
  118.    if RxFuncQuery("VioLoadFuncs") then
  119.       if RxFuncAdd('VioLoadFuncs','RexxVIO','VioLoadFuncs') then
  120.          call RxFuncDrop('VioLoadFuncs')
  121.       else
  122.          call VioLoadFuncs
  123.  
  124.    vioPresent = (RxFuncQuery("VioGetCurType") = 0)
  125.  
  126.    if vioPresent then                                              
  127.       oldCur = VioGetCurType()
  128.  
  129.    insertMode = '-80 -90'
  130.    overwriteMode = '0 -100'   
  131.  
  132.    fileSeparator = ' =;<>|()'
  133.  
  134.    prevLine.0 = 0
  135.  
  136.    cmdList = 'CALL CD CHCP CHDIR CLS COPY DATE DETACH DIR DPATH ECHO',
  137.              'ERASE DEL EXIT FOR IF KEYS MD MKDIR MOVE PATH PAUSE REM',
  138.              'REN RENAME RD RMDIR SET START TIME TYPE VER VERIFY VOL'
  139.                                                         
  140.    shlList = 'ALIAS CD DEF DEFI DEFIN DEFINE KEYS QUIT RX'
  141.                                                           
  142.    invalidCmd = "call SysCurPos origRow + xlen % col, xlen // col;",
  143.                 "call charout 'STDOUT:', '1b'x'[1;31m'||xline'1b'x'[0m';",
  144.                 "xOfs = currOfs + 1"                      
  145.                   
  146.    helpColor1 = '1b'x'[34;47m'
  147.    helpColor2 = '1b'x'[0m'                           
  148.                                                      
  149.    A_F10 = '0071'x                                     
  150.    BKSP = '08'x;                    key._08   = 'backsp'
  151.    CURD = '0050'x;                  key._0050 = 'cdown'
  152.    CURL = '004b'x;                  key._004B = 'cleft'
  153.    CURR = '004d'x;                  key._004D = 'cright'
  154.    CURU = '0048'x;                  key._0048 = 'cup'
  155.    C_CURL = '0073'x;                key._0073 = "ctrlleft"
  156.    C_CURR = '0074'x;                key._0074 = "ctrlright"
  157.    C_END = '0075'x;                 key._0075 = "ctrlend"
  158.    C_HOME = '0077'x;                key._0077 = "ctrlhome"
  159.    C_PGDN = '0076'x
  160.    C_PGUP = '0084'x
  161.    DEL = '0053'x;                   key._0053 = 'del'
  162.    END = '004F'x;                   key._004F = 'end'
  163.    ENTER = '0d'x;                   key._0D   = 'enter'
  164.    ESC = '1b'x;                     key._1B   = 'esc'
  165.    F1 = '003b'x;                    key._003B = 'f1'
  166.    F10 = '0044'x
  167.    F11 = '0085'x 
  168.    F12 = '0086'x                                     
  169.    F2 = '003c'x                                        
  170.    F3 = '003d'x
  171.    F4 = '003e'x   
  172.    F5 = '003f'x               
  173.    F6 = '0040'x
  174.    F7 = '0041'x
  175.    F8 = '0042'x
  176.    F9 = '0043'x
  177.    HOME = '0047'x;                  key._0047 = 'home'
  178.    INS = '0052'x;                   key._0052 = 'ins'
  179.    PGDN = '0051'x                                              
  180.    PGUP = '0049'x                        
  181.    S_TAB = '000F'x;                 key._000F = 'backtab'
  182.    TAB = '09'x;                     key._09   = 'tab'
  183.    SPACE = '20'x;                   key._20   = 'space'                     
  184.                                               
  185.    aliasNames = ''
  186.    profileName = 'profile.shl'
  187.         
  188.    oldDir = directory()               
  189.    secondaryPrompt = SysGetMessage(1093)
  190.    helpString = SysGetMessage(1492)
  191.  
  192.    parse value SysOS2Ver() with osmajor "." osminor       
  193.    if osmajor = '2' & osminor = '30' then /* Warp kludge :-) */
  194.       parse value '3.00' with osmajor "." osminor
  195.    verString = SysGetMessage(1090,,osmajor,osminor)
  196.                                  
  197.    global = 'helpString profileName profileFile verString aliasNames oldDir',
  198.             'cmdList impCD shlList invalidCmd interactive helpColor1 helpColor2',
  199.             'vioPresent insertMode overwriteMode fileSeparator'
  200.    return                                  
  201.  
  202. terminate:
  203.    if vioPresent then
  204.       call VioSetCurType word(oldCur,1),word(oldCur,2),word(oldCur,3),word(oldCur,4)
  205.    return
  206.  
  207. profile:
  208.    interactive = 0                    
  209.    profileFile = SysSearchPath('DPATH',profileName)
  210.    if profileFile \= '' then do             
  211.       do while lines(profileFile) > 0
  212.          line = linein(profileFile)                       
  213.          do while lines(profileFile) > 0 & right(line,1) = ','
  214.             line = left(line,length(line)-1) linein(profileFile)
  215.          end /* do */                              
  216.          if left(line,1) = "'" | left(line,1) = '"' then
  217.             interpret 'call eval' line
  218.          else
  219.             interpret line
  220.       end /* do */                         
  221.       call stream profileFile, 'c', 'close'
  222.       end
  223.    interactive = 1
  224.    return
  225.  
  226. getline:                   
  227.    procedure expose prevLine. key. insertState cmdQueue secondaryPrompt (global)
  228.  
  229.    parse value SysCurPos() with origRow origCol .
  230.    parse value SysTextScreenSize() with row col
  231.  
  232.    parse value origRow origCol '1 0 0 0 0 0' insertState,
  233.          with currRow currCol firstCup currOfs currTab len olen xOfs insert key line
  234.  
  235.    if vioPresent then
  236.       if insert then
  237.          call VioSetCurType word(insertMode,1), word(insertMode,2)
  238.       else
  239.          call VioSetCurType word(overwriteMode,1), word(overwriteMode,2)
  240.  
  241.    if arg(1) \= '' then
  242.       do                           
  243.       line = arg(1)         
  244.       len = length(line)
  245.       call charout "STDOUT:", left(line,max(len,olen))
  246.       if origRow + (origCol + len) % col >= row then
  247.          origRow = row - (origCol + len) % col - 1
  248.       olen = len
  249.       call SysCurPos origRow + (origCol + currOfs) % col, (origCol + currOfs) // col
  250.       end                         
  251.  
  252.    currLine = prevLine.0   
  253.                                 
  254.    do while (key <> "enter")
  255.       lastKey = key              
  256.       key = getKey()
  257.       oline = line
  258.                                     
  259.       select
  260.          when (length(key) = 1) then
  261.             do                             
  262.             if (insert) then
  263.                line = insert(key,line,currOfs)
  264.             else
  265.                line = overlay(key,line,currOfs+1)
  266.  
  267.             currOfs = currOfs + 1
  268.             end                    
  269.  
  270.          when (key = "backsp") then     
  271.             do
  272.             if (currOfs <= 0) then
  273.                iterate
  274.             line = delstr(line,currOfs,1)
  275.             currOfs = currOfs - 1
  276.             end                   
  277.  
  278.          when (key = "space") then                                                       
  279.             do                                                  
  280.             if (insert) then
  281.                line = insert(' ',line,currOfs)              
  282.             else
  283.                line = overlay(' ',line,currOfs+1)
  284.             if line \== oline then
  285.                do                                            
  286.                len = length(line)   
  287.                if len > 0 & currOfs > 1 & currOfs > xOfs then   
  288.                   if left(line,currOfs) == left(oline,currOfs) then
  289.                      call charout "STDOUT:", substr(left(line,max(len,olen)),currOfs+1)
  290.                   else                                     
  291.                      do                                             
  292.                      call SysCurPos origRow, origCol                
  293.                      call charout "STDOUT:", left(line,max(len,olen))
  294.                      end                                            
  295.                else
  296.                   do                    
  297.                   call SysCurPos origRow, origCol
  298.                   call charout "STDOUT:", left(line,max(len,olen))
  299.                   end           
  300.                if origRow + (origCol + len) % col >= row then
  301.                   origRow = row - (origCol + len) % col - 1
  302.                olen = len; oline = line
  303.                end                                                                       
  304.                                                                 
  305.             xOfs = 0; xline = translate(left(line,currOfs),'  ','()'); xlen = lastpos('&',xline)
  306.             if lastpos('|',xline) > xlen then xlen = lastpos('|',xline)
  307.             if xlen > 0 then 
  308.                if verify(reverse(substr(xline,1,xlen-1)),"^") // 2 = 1 then
  309.                   xline = substr(xline,xlen+1)
  310.                else                                          
  311.                   xline = ''                                                                         
  312.             xlen = origCol + currOfs - length(strip(xline,'L')); xline = strip(xline)
  313.             if xline \= '' & pos(' ',xline) = 0 then
  314.                if impCD = 0 | SysSearchPath('CDPATH',xline) = '' then     
  315.                   if wordpos(xline,aliasNames) = 0 then    
  316.                      if wordpos(translate(xline),cmdList shlList) = 0 then
  317.                         if left(xline,1) = '/' | left(xline,1) = '\' | substr(xline,2,1) = ':' then do
  318.                            if stream(xline,'c','query exist') = '' then
  319.                               if stream(xline'.exe','c','query exist') = '' then
  320.                               if stream(xline'.cmd','c','query exist') = '' then
  321.                               if stream(xline'.bat','c','query exist') = '' then
  322.                               if stream(xline'.com','c','query exist') = '' then
  323.                                  interpret invalidCmd
  324.                            end
  325.                         else
  326.                            if SysSearchPath('PATH',xline) = '' then    
  327.                               if SysSearchPath('PATH',xline'.exe') = '' then
  328.                               if SysSearchPath('PATH',xline'.cmd') = '' then
  329.                               if SysSearchPath('PATH',xline'.bat') = '' then
  330.                               if SysSearchPath('PATH',xline'.com') = '' then
  331.                                  interpret invalidCmd
  332.             currOfs = currOfs + 1
  333.             end                 
  334.  
  335.          when (key = "tab") then
  336.             do                                
  337.             if (currOfs <= 0) then
  338.                iterate
  339.             if (currTab \= 0) then
  340.                do
  341.                if (currTab = tree.0) then
  342.                   currTab = 1
  343.                else
  344.                   currTab = currTab+1
  345.                end
  346.             else                                                                                     
  347.                do         
  348.                file = translate(space(translate(getFileSpec(left(line,currOfs)),' "','" '),0),' ','"')
  349.                if (pos('*',file) = 0) then                                
  350.                   file = file'*'
  351.                call SysFileTree expand(translate(file,'\','/')),'tree','O','**-*-'
  352.                if (tree.0 = 0) then
  353.                   iterate
  354.                if (tree.0 = 1 & tree.1'*' = expand(translate(file,'\','/'))) then
  355.                   iterate
  356.                currTab = 1
  357.                end                                                 
  358.                                                          
  359.             newf = filespec("d",file)filespec("p",file)filespec("n",tree.currTab)
  360.             if (pos(' ',newf) > 0) then newf = '"'newf'"'
  361.             subl = left(line,currOfs-length(getFileSpec(left(line,currOfs))))newf
  362.             line = subl||substr(line,currOfs+1)
  363.             currOfs = length(subl)                
  364.             end                               
  365.  
  366.          when (key = "backtab") then          
  367.             do
  368.             if (currOfs <= 0) then
  369.                iterate
  370.             if (currTab \= 0) then
  371.                do
  372.                if (currTab = 1) then
  373.                   currTab = tree.0
  374.                else
  375.                   currTab = currTab-1
  376.                end
  377.             else                   
  378.                do
  379.                file = translate(space(translate(getFileSpec(left(line,currOfs)),' "','" '),0),' ','"')
  380.                if (pos('*',file) = 0) then
  381.                   file = file'*'
  382.                call SysFileTree expand(translate(file,'\','/')),'tree','O','**-*-'
  383.                if (tree.0 = 0) then
  384.                   iterate
  385.                if (tree.0 = 1 & tree.1'*' = expand(translate(file,'\','/'))) then
  386.                   iterate
  387.                currTab = tree.0   
  388.                end
  389.  
  390.             newf = filespec("d",file)filespec("p",file)filespec("n",tree.currTab)
  391.             if (pos(' ',newf) > 0) then newf = '"'newf'"'
  392.             subl = left(line,currOfs-length(getFileSpec(left(line,currOfs))))newf
  393.             line = subl||substr(line,currOfs+1)   
  394.             currOfs = length(subl)
  395.             end
  396.                                 
  397.          when (key = "f1") & (line \= "") then
  398.             do prevLine.0  
  399.                currLine = currLine-1
  400.                if (currLine <= 0) then
  401.                   currLine = prevLine.0
  402.  
  403.                if (left(prevLine.currLine,currOfs) = left(line,currOfs)) then
  404.                   do
  405.                   line = prevLine.currLine
  406.                   leave
  407.                   end
  408.             end                      
  409.  
  410.          when (key = "cright") then
  411.             do
  412.             if (currOfs < len) then
  413.                currOfs = currOfs + 1
  414.             end                                      
  415.  
  416.          when (key = "cleft") then
  417.             do                        
  418.             if (currOfs > 0) then
  419.                currOfs = currOfs - 1
  420.             end
  421.                                  
  422.          when (key = "cup") | (key = "cdown") then
  423.             do
  424.             if (prevLine.0 = 0) then
  425.                iterate          
  426.  
  427.             if (key = "cup") then
  428.                do
  429.                if (firstCup) then
  430.                   firstCup = 0                                  
  431.                else                 
  432.                   currLine = currLine - 1
  433.                end                                  
  434.             else                     
  435.                currLine = currLine + 1
  436.                                      
  437.             if (currLine <= 0) then
  438.                currLine = prevLine.0
  439.  
  440.             if (currLine > prevLine.0) then          
  441.                currLine = 1
  442.                                                      
  443.             line = prevLine.currLine  
  444.             currOfs = length(line)
  445.             end                       
  446.  
  447.          when (key = "del") then
  448.             line = delstr(line,currOfs+1,1)
  449.  
  450.          when (key = "home") then
  451.             currOfs = 0
  452.                                 
  453.          when (key = "end") then
  454.             currOfs = len
  455.                                      
  456.          when (key = "esc") then                                
  457.             do
  458.             line    = ""                                        
  459.             currOfs = 0                             
  460.             end
  461.                                                     
  462.          when (key = "ctrlend") then
  463.             line = left(line,currOfs)
  464.                                   
  465.          when (key = "ctrlhome") then
  466.             do
  467.             line = substr(line,currOfs+1)
  468.             currOfs = 0
  469.             end
  470.  
  471.          when (key = "ctrlleft") & (currOfs > 0) then
  472.             currOfs = wordindex(line,words(left(line,currOfs)))-1
  473.                       
  474.          when (key = "ctrlright") then                       
  475.             do        
  476.             currTab = wordindex(line,words(left(line,currOfs+1))+1)-1
  477.             if (currTab >= 0) then
  478.                currOfs = currTab
  479.             end
  480.  
  481.          when (key = "ins") then                              
  482.             do
  483.             insert = \ insert
  484.             if vioPresent then
  485.                if insert then
  486.                   call VioSetCurType word(insertMode,1), word(insertMode,2)
  487.                else         
  488.                   call VioSetCurType word(overwriteMode,1), word(overwriteMode,2)
  489.             iterate
  490.             end                      
  491.  
  492.          when (abbrev('OSNOWAIT',translate(word(key,1)),3)) then
  493.             call eval subword(key,2)        
  494.  
  495.          when (translate(word(key,1)) = 'TEXT') then
  496.             do
  497.             if (insert) then      
  498.                line = insert(subword(key,2),line,currOfs)
  499.             else
  500.                line = overlay(subword(key,2),line,currOfs+1)
  501.  
  502.             currOfs = currOfs + length(subword(key,2))
  503.             end                                                       
  504.             
  505.          otherwise                                           
  506.             nop
  507.       end                                                    
  508.                           
  509.       if (key \= "tab" & key \= "backtab") then
  510.          currTab = 0                                         
  511.  
  512.       if (line \== oline) then                                
  513.          do
  514.          len = length(line)                                   
  515.          if len > 0 & currOfs > 1 & currOfs > xOfs & length(key) = 1 then
  516.             if left(line,currOfs-1) == left(oline,currOfs-1) then
  517.                call charout "STDOUT:", substr(left(line,max(len,olen)),currOfs)
  518.             else            
  519.                do 
  520.                call SysCurPos origRow, origCol                        
  521.                call charout "STDOUT:", left(line,max(len,olen))
  522.                end
  523.          else
  524.             do                              
  525.             call SysCurPos origRow, origCol
  526.             call charout "STDOUT:", left(line,max(len,olen))
  527.             end
  528.          if origRow + (origCol + len) % col >= row then
  529.             origRow = row - (origCol + len) % col - 1                 
  530.          olen = len               
  531.          end                               
  532.  
  533.       call SysCurPos origRow + (origCol + currOfs) % col, (origCol + currOfs) // col
  534.    end                                                                
  535.                                                                       
  536.    if (line <> "") & (lastKey <> "cup") & (lastKey <> "cdown") then   
  537.       do    
  538.       o = prevLine.0 + 1         
  539.       prevLine.0 = o      
  540.       prevLine.o = line                       
  541.       end                                                    
  542.    else                                       
  543.    if (cmdQueue = 1) & ((lastKey = "cup") | (lastKey = "cdown")) then
  544.       do
  545.       do i = currLine to prevLine.0 - 1                               
  546.          j = i + 1
  547.          prevLine.i = prevLine.j
  548.       end /* do */
  549.       call value 'prevLine.'prevLine.0, line
  550.       end
  551.                                                                         
  552.    call SysCurPos origRow + (origCol + len) % col, (origCol + len) // col
  553.    say                                                                
  554.        
  555.    if (line \= "" & verify(reverse(line),"^") // 2 = 0) then
  556.       do
  557.       call charout "STDOUT:", secondaryPrompt
  558.       line = left(line,len-1) getLine()
  559.       end                                       
  560.                                                                       
  561.    return line                    
  562.                                                                       
  563. /*------------------------------------------------------------------
  564.  * get file spec                           
  565.  *------------------------------------------------------------------*/
  566. getFileSpec:                                                          
  567.    l = length(arg(1))
  568.    do forever                                                         
  569.       select                                    
  570.          when (l < 1) then do; l = 0; leave; end
  571.          when pos(substr(arg(1),l,1), fileSeparator) > 0 then leave
  572.          when (substr(arg(1),l,1) = '"') then l = lastpos('"',arg(1),l-1)
  573.       otherwise                                 
  574.          nop
  575.       end
  576.       l = l - 1                                                       
  577.    end 
  578.    return substr(arg(1),l+1)
  579.                        
  580. /*------------------------------------------------------------------
  581.  * get key     
  582.  *------------------------------------------------------------------*/  
  583. getKey:
  584.    call on halt name ignore                                             
  585.       
  586.    key  = SysGetKey("NOECHO")
  587.    ckey = c2x(key)                                                      
  588.                          
  589.    /*---------------------------------------------------------------
  590.     * get second 'key' if needed                
  591.     *---------------------------------------------------------------*/
  592.    if (ckey = "E0") | (ckey = "00") then        
  593.       ckey = "00" || c2x(SysGetKey("NOECHO"))   
  594.                                 
  595.    /*---------------------------------------------------------------
  596.     * look it up                                
  597.     *---------------------------------------------------------------*/
  598.    ckey = "_"ckey                               
  599.  
  600.    if (symbol("key."ckey) = "LIT") then         
  601.       return key
  602.    else                                         
  603.       return key.ckey
  604.                                                 
  605. /*------------------------------------------------------------------
  606.  * handle break                                 
  607.  *------------------------------------------------------------------*/
  608. ignore:           
  609.    return ""
  610.                        
  611. /*====================================================================
  612.  * Interpret Command-line Arguments.
  613.  *====================================================================*/
  614. doarg:         
  615.    lineArg = arg(1)       
  616.  
  617.    do while lineArg \= ''
  618.       parse value lineArg with switch lineArg                           
  619.      
  620.       select                                                            
  621.          when switch = '/O' | switch = '/o' then insertState = 0
  622.          when switch = '/I' | switch = '/i' then insertState = 1            
  623.          when switch = '/?' then do
  624.             say cmdHelp         
  625.             exit
  626.             end                             
  627.          when switch = '/C' | switch = '/c' then do
  628.             call eval lineArg         
  629.             exit                      
  630.             end     
  631.          when switch = '/K' | switch = '/k' then do
  632.             call eval lineArg
  633.             leave      
  634.             end                          
  635.          when switch = '/P' | switch = '/p' then do
  636.             parse value lineArg with profileName lineArg
  637.             end        
  638.       otherwise                            
  639.          say SysGetMessage(1003) 
  640.          exit 1
  641.       end  /* select */
  642.                                                 
  643.    end /* do */
  644.                   
  645.    return                      
  646.                           
  647. /*====================================================================
  648.  * A cmd.exe-like Command Evaluator.
  649.  *====================================================================*/
  650. eval:                                                         
  651.    cmdLine = strip(arg(1),'L')                           
  652.    needcr = 1; xlen = length(cmdLine); xpos = 1
  653.                                                                             
  654.    do while xpos <= xlen
  655.       /* parsing command line */                                            
  656.       inStr = 0; inSub = 0; xcur = xpos
  657.       do while xpos <= xlen                 
  658.          ch = substr(cmdLine,xpos,1); xpos = xpos + 1
  659.                                             
  660.          if ch = '"' then inStr = inStr && 1
  661.          else                           
  662.          if \inStr then do            
  663.             if ch = '^' then xpos = xpos + 1
  664.             else                                                  
  665.             if ch = '&' & inSub = 0 then leave
  666.             else                        
  667.             if ch = '(' then inSub = inSub + 1
  668.             else                        
  669.             if ch = ')' then inSub = inSub - 1
  670.             end                  
  671.       end /* do */                         
  672.       parse value substr(cmdLine,xcur,xpos-xcur) with cmd args
  673.                                                 
  674.       if right(args,1) = '&' & right(args,2) \= '^&' then
  675.          args = left(args,length(args)-1)       
  676.                                
  677.       ucmd = translate(cmd)    
  678.                                
  679.       if args = '' & impCD = 1 then do
  680.          curDir = directory()
  681.          if dir(cmd) \= '' then do                            
  682.             oldDir = curDir                              
  683.             iterate                                           
  684.             end                                                         
  685.          end                                                                
  686.  
  687.       select                   
  688.          when (wordpos(cmd,arg(2)) = 0) & (wordpos(cmd,aliasNames) > 0) then do
  689.             call eval substitute(aliasStem.cmd,cmd args), arg(2) cmd
  690.             needcr = 0                     
  691.             end                       
  692.          when wordpos(ucmd,shlList) > 0 then
  693.             select
  694.                when (ucmd = 'CD') then call cd args
  695.                when (ucmd = 'RX') then do                         
  696.                   signal on syntax name error
  697.                   interpret args                                  
  698.                   needcr = 0            
  699.                   end                        
  700.                when (ucmd = 'ALIAS') then call alias args
  701.                when (ucmd = 'KEYS') then   
  702.                   if translate(args) = 'LIST' then
  703.                      do key = 1 to prevLine.0
  704.                         say right(key,5)':' prevLine.key
  705.                      end /* do */               
  706.                   else
  707.                      ''cmd args   
  708.                when abbrev('DEFINE',ucmd,3) then do
  709.                   needcr = 0  
  710.                   parse value args with key rest
  711.                   if key = '/?' then do
  712.                      say defHelp
  713.                      iterate                                  
  714.                      end                                 
  715.                   if length(key) > 1 then                               
  716.                      if symbol(translate(key,'_','-')) = 'VAR' then
  717.                         key = value(translate(key,'_','-'))             
  718.                      else do
  719.                         say SysGetMessage(1003)     
  720.                         iterate        
  721.                         end                    
  722.                   if rest \= '' then       
  723.                      call value 'key._'c2x(key), rest
  724.                   else                  
  725.                      interpret 'drop key._'c2x(key)
  726.                   end                  
  727.                when (ucmd = 'QUIT') then return 0                 
  728.             otherwise                   
  729.             end      
  730.          when wordpos(ucmd, cmdList) > 0 | left(ucmd,1) = '(' then
  731.             cmd args  
  732.       otherwise
  733.          'call' cmd args
  734.       end /* select */
  735.    end              
  736.  
  737.    if arg(1) \= '' & interactive & needcr then say
  738.                     
  739.    return 1                   
  740.                                
  741. error:                     
  742.    say 'REX'right(rc,4,'0')':' errortext(rc)nl
  743.    if condition('I') = 'SIGNAL' then
  744.       signal loop
  745.    else                                        
  746.       return  
  747.                                                                         
  748. substitute: 
  749.    procedure
  750.    symb = arg(1); actual = arg(2); xpos = 1; xlen = length(symb); r = ''; inSubst = 0
  751.    do while xpos <= xlen                            
  752.       ch = substr(symb,xpos,1); xpos = xpos + 1
  753.       if ch = '^' then do                           
  754.          r = r || substr(symb,xpos,1)
  755.          xpos = xpos + 1                       
  756.          end                      
  757.       else                               
  758.       if ch = '%' & inSubst = 0 then inSubst=1
  759.       else                
  760.       if inSubst = 1 then do            
  761.          inSubst = 0
  762.          if pos(ch,0123456789) > 0 then
  763.             if substr(symb,xpos,1) = '*' then do
  764.                r = r || subword(actual,ch+1)
  765.                xpos = xpos+1              
  766.                end     
  767.             else    
  768.                r = r || word(actual,ch+1)
  769.          else                           
  770.          if ch = '*' then
  771.             r = r || subword(actual,2)  
  772.          else
  773.             r = r'%'ch     
  774.          end     
  775.       else                 
  776.          r = r || ch                               
  777.    end /* do */                                
  778.    if inSubst = 1 then              
  779.       r = r'%'                                 
  780.    return r
  781.  
  782. expand: 
  783.    procedure
  784.    args = arg(1); xpos = pos('%',args)+1
  785.    if xpos > 1 then do
  786.       ypos = pos('%',args,xpos)
  787.       if ypos > 0 then do
  788.          envi = substr(args,xpos,ypos-xpos)
  789.          valu = value(envi,,'OS2ENVIRONMENT')
  790.          if valu = '' then
  791.             args = left(args,xpos-1) || envi || expand(substr(args,ypos))
  792.          else
  793.             args = left(args,xpos-2) || valu || expand(substr(args,ypos+1))
  794.          end
  795.       end
  796.    return args
  797.  
  798. dir: 
  799.    procedure                         
  800.    parse value expand(arg(1)) with args                
  801.    if left(args,1) = '"' then args = strip(args,,'"')
  802.    if directory(args) = '' then do       
  803.       cdpath = value('CDPATH',,'OS2ENVIRONMENT')
  804.       do while cdpath \= ''
  805.          parse value cdpath with path ';' cdpath
  806.          if pos(right(path,1),'\/') = 0 then
  807.             path = path'\'
  808.          if directory(path||args) \= '' then do
  809.             return directory()       
  810.             end                     
  811.       end /* do */                   
  812.       return ''                           
  813.       end              
  814.    return directory()                     
  815.                        
  816. cd:                                     
  817.    parse value arg(1) with args
  818.                                         
  819.    curDir = directory() 
  820.    select                               
  821.       when args = '-' then
  822.          call directory oldDir
  823.       when args = '/?' then do                     
  824.          '@CD /?'                              
  825.          say cdHelp                                
  826.          end
  827.       when args = '' | right(args,1) = ':' then do
  828.          say directory(args)
  829.          call directory(curDir)
  830.          end                         
  831.    otherwise         
  832.       if dir(args) = '' then do      
  833.          say SysGetMessage(0003)
  834.          needcr = 0          
  835.          end
  836.    end  /* select */
  837.    oldDir = curDir 
  838.       
  839.    return          
  840.                                      
  841. alias: 
  842.    procedure expose aliasHelp aliasNames aliasStem.
  843.          
  844.    parse value arg(1) with subcmd '>' file
  845.                        
  846.    select      
  847.       when translate(subcmd) = 'LIST' then
  848.          if (file \= '') then do        
  849.             do alias = 1 to words(aliasNames)
  850.                name = word(aliasNames,alias)
  851.                call lineout file,name'='aliasStem.name
  852.             end /* do */
  853.             call stream file,'c','close'
  854.             end
  855.          else                                      
  856.             do alias = 1 to words(aliasNames)
  857.                name = word(aliasNames,alias)
  858.                say right(alias,4) left(name,10) '=' aliasStem.name
  859.             end
  860.       when left(subcmd,1) = '@' then do
  861.          file = substr(subcmd,2)
  862.          do while lines(file) > 0    
  863.             call addalias linein(file)
  864.          end /* do */        
  865.          call stream file,'c','close'
  866.          end
  867.       when subcmd = '/?' then do
  868.          say aliasHelp
  869.          end       
  870.    otherwise
  871.       call addalias arg(1)
  872.    end /* select */
  873.    return                           
  874.  
  875. addalias:      
  876.    parse value arg(1) with alias '=' cmd
  877.    alias = strip(alias)
  878.    if cmd \= '' then do
  879.       if wordpos(alias,aliasNames) = 0 then
  880.          aliasNames = aliasNames alias
  881.       aliasStem.alias = cmd
  882.       end
  883.    else do
  884.       parse value aliasNames with first (alias) last
  885.       aliasNames = first last
  886.       end
  887.    return
  888.  
  889.